<template>
  <div id="hy-swiper">
    <div
      class="swiper"
      @touchstart.passive="touchStart"
      @touchmove.passive="touchMove"
      @touchend.passive="touchEnd"
      ref="swiperWrapRef"
    >
      <!-- <slot name="slide-image"></slot> -->
      <slot></slot>
      
    </div>
    <slot name="indicator"> </slot>
    <div class="indicator">
      <slot name="indicator" v-if="showIndicator && slideCount > 1">
        <div
          v-for="(item, index) in slideCount"
          class="indi-item"
          :class="{ active: index === currentIndex - 1 }"
          :key="index"
        ></div>
      </slot>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from "vue";

const slideCount = ref(0); // 元素个数
let totalWidth = 0; // swiper的宽度
let swiperStyle: any = {}; // swiper样式
let currentIndex = ref(1); // 当前的index
let scrolling = false; // 是否正在滚动
let playTimer: any = null;
let startX = 0;
let currentX = 0;
let distance = 0;

const swiperWrapRef = ref(null);

const props = defineProps({
  interval: {
    type: Number,
    default: 3000,
  },
  animDuration: {
    type: Number,
    default: 300,
  },
  moveRatio: {
    type: Number,
    default: 0.25,
  },
  showIndicator: {
    type: Boolean,
    default: true,
  },
});

const emit = defineEmits(["transitionEnd"]);

onMounted(() => {
  // 1.操作DOM, 在前后添加Slide
  setTimeout(() => {
    handleDom();

    // 2.开启定时器
    startTimer();
  }, 3000);
  // console.log("onMounted");
});
/**
 * 定时器操作
 */
const startTimer = function () {
  playTimer = window.setInterval(() => {
    currentIndex.value++;
    scrollContent(-currentIndex.value * totalWidth);
  }, props.interval);
};

const stopTimer = function () {
  window.clearInterval(playTimer);
};

/**
 * 滚动到正确的位置
 */
const scrollContent = function (currentPosition: any) {
  // 0.设置正在滚动
  scrolling = true;

  // 1.开始滚动动画
  swiperStyle.transition = "transform " + props.animDuration + "ms";
  setTransform(currentPosition);

  // 2.判断滚动到的位置
  checkPosition();

  // 4.滚动完成
  scrolling = false;
};

/**
 * 校验正确的位置
 */
const checkPosition = function () {
  window.setTimeout(() => {
    // 1.校验正确的位置
    swiperStyle.transition = "0ms";
    if (currentIndex.value >= slideCount.value + 1) {
      currentIndex.value = 1;
      setTransform(-currentIndex.value * totalWidth);
    } else if (currentIndex.value <= 0) {
      currentIndex.value = slideCount.value;
      setTransform(-currentIndex.value * totalWidth);
    }

    // 2.结束移动后的回调
    emit("transitionEnd", currentIndex.value - 1);
  }, props.animDuration);
};

/**
 * 设置滚动的位置
 */
const setTransform = function (position: any) {
  swiperStyle.transform = `translate3d(${position}px, 0, 0)`;
  swiperStyle["-webkit-transform"] = `translate3d(${position}px), 0, 0`;
  swiperStyle["-ms-transform"] = `translate3d(${position}px), 0, 0`;
};

/**
 * 操作DOM, 在DOM前后添加Slide
 */
const handleDom = function () {
  // 1.获取要操作的元素
  // let swiperEl = document.querySelector(".swiper");
  // console.log(swiperWrapRef.value);

  let swiperEl: any = swiperWrapRef.value;
  let slidesEls = [];
  if (swiperEl) slidesEls = swiperEl.getElementsByClassName("slide");

  // 2.保存个数
  slideCount.value = slidesEls.length;
  // console.log(slidesEls, slideCount.value);

  // 3.如果大于1个, 那么在前后分别添加一个slide
  if (slideCount.value > 1) {
    let cloneFirst = slidesEls[0].cloneNode(true);
    let cloneLast = slidesEls[slideCount.value - 1].cloneNode(true);
    swiperEl.insertBefore(cloneLast, slidesEls[0]);
    swiperEl.appendChild(cloneFirst);
    totalWidth = swiperEl.offsetWidth;
    swiperStyle = swiperEl.style;
  }

  // 4.让swiper元素, 显示第一个(目前是显示前面添加的最后一个元素)
  setTransform(-totalWidth);
};

/**
 * 拖动事件的处理
 */
const touchStart = function (e: any) {
  // 1.如果正在滚动, 不可以拖动
  if (scrolling) return;

  // 2.停止定时器
  stopTimer();

  // 3.保存开始滚动的位置
  startX = e.touches[0].pageX;
};

const touchMove = function (e: any) {
  // 1.计算出用户拖动的距离
  currentX = e.touches[0].pageX;
  distance = currentX - startX;
  let currentPosition = -currentIndex.value * totalWidth;
  let moveDistance = distance + currentPosition;

  // 2.设置当前的位置
  setTransform(moveDistance);
};

const touchEnd = function () {
  // 1.获取移动的距离
  let currentMove = Math.abs(distance);

  // 2.判断最终的距离
  if (distance === 0) {
    return;
  } else if (distance > 0 && currentMove > totalWidth * props.moveRatio) {
    // 右边移动超过0.5
    currentIndex.value--;
  } else if (distance < 0 && currentMove > totalWidth * props.moveRatio) {
    // 向左移动超过0.5
    currentIndex.value++;
  }

  // 3.移动到正确的位置
  scrollContent(-currentIndex.value * totalWidth);

  // 4.移动完成后重新开启定时器
  startTimer();
};

/**
 * 控制上一个, 下一个
 */
const previous = function () {
  changeItem(-1);
};

const next = function () {
  changeItem(1);
};

const changeItem = function (num: number) {
  // 1.移除定时器
  stopTimer();

  // 2.修改index和位置
  currentIndex.value += num;
  scrollContent(-currentIndex.value * totalWidth);

  // 3.添加定时器
  startTimer();
};
</script>

<style lang="less" scoped>
#hy-swiper {
  overflow: hidden;
  position: relative;
}

#hy-swiper .swiper {
  display: flex;
}

.swiper{
  height: auto;
}

.indicator {
  display: flex;
  justify-content: center;
  position: absolute;
  width: 100%;
  bottom: 8px;
}

.indi-item {
  box-sizing: border-box;
  width: 8px;
  height: 8px;
  border-radius: 4px;
  background-color: #fff;
  line-height: 8px;
  text-align: center;
  font-size: 12px;
  margin: 0 5px;
}

.indi-item.active {
  background-color: rgba(212, 62, 46, 1);
}
.slide {
  width: 100%;
  flex-shrink: 0;
}

.slide img {
  width: 100%;
}
</style>
